// #ifdef H5
// @ts-ignore
import { publish, subscribe, unsubscribe, client, subject } from './browser';
// #endif

// #ifdef MP-WEIXIN
// @ts-ignore
import { publish, subscribe, unsubscribe, socketTask, subject } from './wechat.mp';
// #endif

import { TIMEOUT, pool } from './pool';

import { createMachine, interpret } from 'xstate';
import { v4 } from 'uuid'

let queue = [] as [key: string, data: any, handler: (obj : any) => void, onTimeout: () => void][];

function isReady() {
  let isReady = false;
  // #ifdef H5
  isReady = client.isConnected();
  // #endif
  // #ifdef MP-WEIXIN
  isReady = socketTask.readyState === 1;
  // #endif
  return isReady;
}
// 正式环境formal
//测试环境  test
function execQueue() {
  if (isReady()) {
    queue.forEach((value) => {
      toPublish(...value);
    });
    queue = [];
  } else {
    setTimeout(execQueue, 100);
  }
}

function toPublish(
  key : string,
  data : any,
  handler : (obj : any) => void,
  // onTimeout: () => void = () => errorToast('通讯超时'),
) {
  if (!isReady()) {
    if (queue.length === 0) {
      setTimeout(execQueue, 100);
    }
    queue.push([key, data, handler]);
    return;
  }

  if (pool[key]) {
    return;
  }

  data.msg_id = Date.now().toString().slice(0, -3);
  var token = ''
  if (uni.getStorageSync('identification')) {
    token = uni.getStorageSync('identification')
  } else {
    token = v4()
    uni.setStorageSync('identification', v4())
  }
  const topicMachine = createMachine(
    {
      context: {
        key,
        token,
        data,
      },
      initial: 'unsubscribed',
      states: {
        unsubscribed: {
          entry: 'toSubscribe',
          on: {
            NEXT: 'subscribed',
          },
        },
        subscribed: {
          entry: 'toPublish',
          on: {
            NEXT: 'published',
          },
        },
        published: {
          on: {
            NEXT: 'responsed',
          },
        },
        responsed: {
          type: 'final',
          entry: 'toUnsubscribe',
        },
      },
    },
    {
      actions: {
        toSubscribe(context) {
          const topic = `formal/v1/${context.key}/client/${context.token}`;
          subscribe(topic);
        },
        toPublish(context) {
          const topic = `formal/v1/${context.key}/server/${context.token}`;
          publish(topic, context.data);
        },
        toUnsubscribe(context) {
          delete pool[key];
          const topic = `formal/v1/${context.key}/client/${context.token}`;
          unsubscribe(topic);
        },
      },
    },
  );
  // 解释状态机
  const machineService = interpret(topicMachine);

  pool[key] = {
    machineService,
    onMsg(obj : any) {
      clearTimeout(timeoutID);
      uni.hideLoading();
      handler(obj);
    },
  };
  // 启动状态机
  machineService.start();
  //取消订阅定时器
  const timeoutID = setTimeout(() => {
    unsubscribe(`formal/v1/${key}/client/${token}`);
    delete pool[key];
    uni.hideLoading();
  }, TIMEOUT);
}

export { toPublish, publish, subscribe, unsubscribe, subject };